using System;
using System.Threading;
using CriticalSystems.Instrumentation.Internal;

namespace CriticalSystems.Instrumentation.TraceWriters
{
    /// <summary>
    /// A wrapper for a simple trace writer that only support the void Write(string text) method. 
    /// </summary>
    public class SimpleTraceWriterWrapper : ITraceWriter
    {
        private readonly ITraceWriter writer;

        /// <summary>
        /// Initializes a new instance of the <see cref="SimpleTraceWriterWrapper"/> class.
        /// </summary>
        /// <param name="writer">The writer.</param>
        public SimpleTraceWriterWrapper(ITraceWriter writer)
        {
            this.writer = writer;
        }

        /// <summary>
        /// Gets the flags.
        /// </summary>
        /// <value>The flags.</value>
        public TracingFlags Flags
        {
            get { return this.writer.Flags; }
        }

        /// <summary>
        /// Writes the specified trace type.
        /// </summary>
        /// <param name="traceType">Type of the trace.</param>
        /// <param name="indent">The indent.</param>
        /// <param name="instance">The instance.</param>
        /// <param name="type">The type.</param>
        /// <param name="method">The method.</param>
        /// <param name="text">The text.</param>
        public void Write(TraceType traceType, int indent, string instance, string type, string method, string text)
        {
            string fullText;
            var typeText = GetTypeText(type, instance);
            if (text == null)
            {
                fullText = string.Format("\t{0}\t[{1}]\t{2} {3} {4}.{5}", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fff"),
                                         Thread.CurrentThread.ManagedThreadId, GetTracePrefix(traceType), GetIndentString(indent, '.'), typeText,
                                         method);                
            }
            else
            {
                fullText = string.Format("\t{0}\t[{1}]\t{2} {3} {4}.{5} : {6}", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fff"),
                                         Thread.CurrentThread.ManagedThreadId, GetTracePrefix(traceType), GetIndentString(indent, '.'), typeText,
                                         method, text);
            }
            this.writer.Write(fullText);
        }

        public static string GetTypeText(string type, string instance)
        {
            var typeText = type;
            if (string.IsNullOrEmpty(instance))
            {
                typeText = string.Format("{0}:{1}", instance, type);
            }
            return typeText;
        }

        /// <summary>
        /// Forms a string of characters representing an indentatio
        /// </summary>
        /// <param name="indent">The indent.</param>
        /// <param name="character">The character.</param>
        /// <returns></returns>
        public static string GetIndentString(int indent, char character)
        {
            return indent > 0 ? string.Empty.PadRight(indent-1, character) : string.Empty;
        }

        /// <summary>
        /// Gets an eyecatching prefix for a trace line depending on the type of trace.
        /// </summary>
        /// <param name="traceType">Type of the trace.</param>
        /// <returns></returns>
        public static string GetTracePrefix(TraceType traceType)
        {
            string prefix;
            switch (traceType)
            {
                case TraceType.In:
                    prefix = "---->";
                    break;
                case TraceType.Out:
                    prefix = "<----";
                    break;
                case TraceType.Info:
                    prefix = "-----";
                    break;
                case TraceType.Warning:
                    prefix = "WARN ";
                    break;
                case TraceType.Error:
                    prefix = "ERROR";
                    break;
                default:
                    prefix = "-----";
                    break;
            }
            return prefix;
        }

        /// <summary>
        /// Writes the specified text - not implemented
        /// </summary>
        /// <param name="text">The text.</param>
        public void Write(string text)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Gets a value indicating whether this is a simple writer - false in this case.
        /// </summary>
        /// <value><c>true</c> if [simple writer]; otherwise, <c>false</c>.</value>
        public bool SimpleWriter
        {
            get { return false; }
        }
    }
}